<?php

namespace App\Http\Controllers\Api;

use App\Exceptions\CouponCodeUnavailableException;
use App\Exceptions\InvalidRequestException;
use App\Http\Requests\ApplyRefundRequest;
use App\Http\Requests\OrderRequest;
use App\Jobs\CloseOrder;
use App\Model\Order;
use App\Model\ProductSku;
use App\Model\UserAddress;
use App\Services\OrderService;
use App\Transformers\OrderTransformer;
use Carbon\Carbon;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;

class OrdersController extends Controller
{

    public function index(Request $request)
    {
        $user   = auth('api')->user();

        $orders = Order::query()// 使用 with 方法预加载，避免N + 1问题
            ->with(['items.product', 'items.productSku'])
            ->where('user_id', $user->id)
            ->orderBy('created_at', 'desc')
            ->paginate();
        return $this->response->paginator($orders,new OrderTransformer());
    }
    // 评价
    public function review(Order $order)
    {
        // 校验权限
        $this->authorize('own', $order);
        // 判断是否已经支付
        if (!$order->paid_at) {
            throw new InvalidRequestException('该订单未支付，不可评价');
        }
        // 使用 load 方法加载关联数据，避免 N + 1 性能问题
        return view('orders.review', ['order' => $order->load(['items.productSku', 'items.product'])]);
    }
    //提交评价
    public function sendReview(Order $order, SendReviewRequest $request)
    {
        // 校验权限
        $this->authorize('own', $order);
        if (!$order->paid_at) {
            throw new InvalidRequestException('该订单未支付，不可评价');
        }
        // 判断是否已经评价
        if ($order->reviewed) {
            throw new InvalidRequestException('该订单已评价，不可重复提交');
        }
        $reviews = $request->input('reviews');
        // 开启事务
        \DB::transaction(function () use ($reviews, $order) {
            // 遍历用户提交的数据
            foreach ($reviews as $review) {
                $orderItem = $order->items()->find($review['id']);
                // 保存评分和评价
                $orderItem->update([
                    'rating'      => $review['rating'],
                    'review'      => $review['review'],
                    'reviewed_at' => Carbon::now(),
                ]);
            }
            // 将订单标记为已评价
            $order->update(['reviewed' => true]);
        });

        return redirect()->back();
    }

    public function show($id)
    {
        $order = Order::findOrFail($id)->load(['items.productSku', 'items.product']);
        return $this->response->item($order,new OrderTransformer());
    }

    public function received($id,Request $request)
    {
        $user   = auth('api')->user();

        $order = $user->orders->find($id);
        // 判断订单的发货状态是否为已发货
        if ($order->ship_status !== Order::SHIP_STATUS_DELIVERED) {
            throw new InvalidRequestException('发货状态不正确');
        }
        // 更新发货状态为已收到
        $res = $order->update(['ship_status' => Order::SHIP_STATUS_RECEIVED]);
        return responseJson(201,$res,'success');
    }

    // applyRefund() 方法作为提交退款申请的接口
    public function applyRefund($order, ApplyRefundRequest $request)
    {
        // 校验订单是否属于当前用户
        $user   = auth('api')->user();
        $order = $user->orders->find($order);

        // 判断订单是否已付款
        if (!$order->paid_at) {
            throw new InvalidRequestException('该订单未支付，不可退款');
        }
        // 判断订单退款状态是否正确
        if ($order->refund_status !== Order::REFUND_STATUS_PENDING) {
            throw new InvalidRequestException('该订单已经申请过退款，请勿重复申请');
        }
        // 将用户输入的退款理由放到订单的 extra 字段中
        $extra                  = $order->extra ?: [];
        $extra['refund_reason'] = $request->input('reason');
        // 将订单退款状态改为已申请退款
        $order->update([
            'refund_status' => Order::REFUND_STATUS_APPLIED,
            'extra'         => $extra,
        ]);

        return $order;
    }
    public function store(OrderRequest $request){
        $user = $request->user();
        //开启一个数据库事务
        $order = DB::transaction(function () use ($user ,$request){
            $address = UserAddress::find($request->input('address_id'));
            $address->update(['last_used_at'=>Carbon::now()]);
            $order = new Order([
                'address'      => [ // 将地址信息放入订单中
                    'address'       => $address->full_address,
                    'zip'           => $address->zip,
                    'contact_name'  => $address->contact_name,
                    'contact_phone' => $address->contact_phone,
                ],
                'remark'=> $request->input('remark'),
                'total_amount'=>0,
            ]);
            $order->user()->associate($user);
            $order->save();

            $total_amount = 0;
            $items = $request->input('items');
            foreach ($items as $data){
                $sku = ProductSku::find($data['sku_id']);
                $item = $order->items()->make([
                    'amount'=> $data['amount'],
                    'price' => $sku->price,
                ]);

                $item->product()->associate($sku->product);
                $item->productSku()->associate($sku);
                $item->save();
                $total_amount += $sku->price * $data['amount'];
                if($sku->decreaseStock($data['amount']) <= 0){
                    throw new InvalidRequestException('库存不足');
                }
            }

            $order->update(['total_amount'=>$total_amount]);

            $skuIds = collect($request->input('items'))->pluck('sku_id');
            $user->cartItems()->whereIn('product_sku_id', $skuIds)->delete();

            return $order;

        });

        $this->dispatch(new CloseOrder($order,config('app.order_ttl')));

        return $order;
    }


    public function store1(OrderRequest $request,OrderService $orderService)
    {
        $user   = auth('api')->user();
        $address = UserAddress::find($request->input('address_id'));
        $coupon  = null;

        // 如果用户提交了优惠码
        if ($code = $request->input('coupon_code')) {
            $coupon = CouponCode::where('code', $code)->first();
            if (!$coupon) {
                throw new CouponCodeUnavailableException('优惠券不存在');
            }
        }
        // 参数中加入 $coupon 变量
        return $orderService->store($user, $address, $request->input('remark'), $request->input('items'), $coupon);

    }
}
